#!/usr/bin/python




import re, tarfile, glob, os, time, datetime, logging, sys
from time import sleep
from tarfile import TarError
###################################################################################################
#
#                                          TESTING-FUNCTIONS:
#
###################################################################################################


#1
#Check regex matching
def checkMatching():
    path_to_backup = os.getenv('TRACE')
    files = glob.glob(os.path.join(path_to_backup, '*'))
    pattern = '[\w]*?\.TRC[\d]*'
    regex = re.compile(pattern) 
    counter = 0
    for f in files:
        if isMatch(os.path.basename(f), regex): 
            counter += 1
    print(counter)

#2
#Check archiving
def checkArchiving():
    tfile = tarfile.open('something.tar.gz', 'w:gz')
    tfile.add('123kdd.txt')
    tfile.close()
#3
#Check yesterdayDate
def checkYesterdayDate():
    path_to_backup = os.getenv('TRACE')
    files = glob.glob(os.path.join(path_to_backup, '*'))
    for f in files:
        if os.path.isdir(f):
            continue
        dt_mtime = datetimeFromFile(f)
        dt_yesterday = yesterdayDate()
        if isFromYesterday(dt_mtime, dt_yesterday):
            print(dt_mtime)


###################################################################################################
#
#                                          MAIN-FUNCTIONS:
#
###################################################################################################

#1
#convert modification time stamp of file to datetime obj

def datetimeFromFile(f):
    stats = os.stat(f)
    time_stamp = stats.st_mtime
    #time_stamp = os.stat(f).st_mtime
    dt_mtime = datetime.datetime.fromtimestamp(time_stamp)
    return dt_mtime

#2
#find yesterdays date - we need to compare days in order to back up previous day
def yesterdayDate():
    dt_today = datetime.datetime.today()
    dt_delta = datetime.timedelta(days=1)
    dt_yesterday = dt_today - dt_delta
    return dt_yesterday

#3
#Check if file is from previous day:
#this assumes script is run daily. if run at monthly intervals could potentially mistake day from
#previous month is yesterday, when in fact not
def isFromYesterday(dt_mtime, dt_yesterday):
    if dt_mtime.day == dt_yesterday.day:
        return True
    else:
        return False

#4
#check file names for pattern match
'''this function seems redundant'''
def build_regexs(pattern_list):
    '''
    build a list of compiled patterns into regex including flags to feed to isMatch()
    '''
    regex_list = []
    for pattern, flags in pattern_list:
        regex_list.append(re.compile(pattern, flags))
    return regex_list
def isMatch(f_name, regexs):
    '''
    take file name and compiled regex list and test all regexs against file name
    '''
    for regex in regexs:
        is_match = re.match(regex, f_name)
        if is_match:
            return True
    return False

def hasPerm(file_path):
    if not (os.access(file_path, os.W_OK) and os.access(file_path, os.R_OK)):
        return False
    return True    

def logger_init():
    log_file = 'trace_pybackup.log'
    logger = logging.getLogger('backup_logger')
    logger.setLevel(logging.WARNING)
    frmt = logging.Formatter(fmt='%(asctime)s - %(levelname)s - %(message)s', datefmt='%d.%m.%Y %H.%M.%S')
    try:
	#return intended logger
        hndl = logging.FileHandler(log_file, mode='w')
	hndl.setFormatter(frmt)
	logger.addHandler(hndl)
    except IOError, e:
	#On failure return module logger for module function log messages
	logger = logging
        print('failed to Create logging file: %s'% (log_file))
    return logger


###################################################################################################
#
#                                              MAIN: 
#
###################################################################################################

def main_checking():
    checkMatching()
    checkArchiving()
    checkYesterdayDate()

def main():

    #####DEFINITIONS:
    logger = logger_init()
    pattern_list = [ (r'^[\w]*?\.TRC[\w]*$', re.I|re.S), 
    (r'^IPM_IN_.*$', re.I|re.S),
    (r'^.*?\.err$', re.I|re.S),
    (r'^sky_miles.*$',re.I|re.S),
    (r'^.*?\.log$',re.I|re.S),
    (r'^DAILY_CREDIT_CUTOFF.*$',re.I|re.S),
    (r'^CREDIT_ACTIVITY.*$',re.I|re.S),
    (r'^KNET_FILE.*$',re.I|re.S),
    (r'^KNET_KPAY_FILE.*$',re.I|re.S),
    (r'^MER_FILE.*$',re.I|re.S),
    (r'^MERCHANT_SETTLEMENT.*$',re.I|re.S)]
    regex_list = build_regexs(pattern_list)
    if not regex_list:
        logger.error('##1 Could not build search patterns.')
        sys.exit(1)
    #path_to_backup = '/pcard17/trace'
    path_to_backup = '/pwrcard/home/usr/trace'
    #EXIT IF: path is invalid/does not exist
    if not os.path.isdir(path_to_backup):
        #add logger msg for invalid trace directory
        logger.critical('##2 Directory to backup (%s) does not exist', path_to_backup)
        sys.exit(1)
    if not hasPerm(path_to_backup):
        logger.critical('##3 No read/write permissions for %s'% path_to_backup)
        sys.exit(1)
    os.chdir(path_to_backup) 
    files = glob.glob(os.path.join(path_to_backup, '*'))
    todayTimeStamp = time.time()
    #day = number of hours per day * number of minutes per hour * number of seconds per minute
    #get rid of this and use proper datetime objects and delta time
    day = 24*60*60
    yesterdayTimeStamp = todayTimeStamp - day
    yesterday = time.localtime(yesterdayTimeStamp)
    file_timestamp = time.strftime('%d.%m.%Y', yesterday)
    archive_name = '%s.tar.gz'%(file_timestamp)
    archive_counter = 0
    to_delete = []
    #left_over = []
    
    
    #CREATE TARFILE - remove if no files archived
    try: 
        tar = tarfile.open(archive_name, 'w:gz')
    except (TarError, OSError), e: 
        logger.critical('##4 Failed to open (%s) archive file -- Error: %s'% (archive_name, str(e)))
        sys.exit(1)


    for abs_file in files:
        #pass all directories
        if os.path.isdir(abs_file):
            logger.warn('##5 Skipping %s because directory'% (os.path.basename(abs_file)))
            continue
        elif not hasPerm(abs_file):
            logger.warn('##6 %s no read/write permissions, continuing with dependance on directory permissions.'% (os.path.basename(abs_file)))
        rel_file = os.path.basename(abs_file)
        dt_file = datetimeFromFile(rel_file)
        dt_yesterday = yesterdayDate()
        #only archive if filename matches pattern and has same 'day' as yesterday  ---- IE: 24==24
        if isMatch(rel_file, regex_list) and isFromYesterday(dt_file, dt_yesterday):
            archive_counter += 1
            to_delete.append(abs_file)
            try: 
                tar.add(rel_file)
            except (TarError, OSError), e: 
                logger.error('##7 Failed to archive: %s -- Error: %s'% (rel_file, str(e)))
                to_delete.pop()
###################################################################################################
#
#                                              CLEAN UP:
#
###################################################################################################


    tar.close()
    if archive_counter == 0:                        #meaning no files were archived
        try: 
            logger.warning('no files found')
            os.remove(archive_name)
        except (OSError, Exception), e: 
            logger.warning('##10 No files to archive --- Failed to delete empty archive: %s'% (archive_name))
            sys.exit(1)
    #safe to assume files archived and we can delete them now 
    else:
        #make try catch blocks into decorator functions where we pass Exception type and place code between these try catches into methods to decorate
        try:
            for abs_file in to_delete:
                os.remove(abs_file)
        except OSError, e:
            logger.error('##11 Error while deleting %s, please manually remove it'% (abs_file))


if __name__ == '__main__':
    main()
